home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / r_efrag.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  5KB  |  277 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_efrag.c
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. mnode_t    *r_pefragtopnode;
  26.  
  27.  
  28. //===========================================================================
  29.  
  30. /*
  31. ===============================================================================
  32.  
  33.                     ENTITY FRAGMENT FUNCTIONS
  34.  
  35. ===============================================================================
  36. */
  37.  
  38. efrag_t        **lastlink;
  39.  
  40. vec3_t        r_emins, r_emaxs;
  41.  
  42. entity_t    *r_addent;
  43.  
  44.  
  45. /*
  46. ================
  47. R_RemoveEfrags
  48.  
  49. Call when removing an object from the world or moving it to another position
  50. ================
  51. */
  52. void R_RemoveEfrags (entity_t *ent)
  53. {
  54.     efrag_t        *ef, *old, *walk, **prev;
  55.     
  56.     ef = ent->efrag;
  57.     
  58.     while (ef)
  59.     {
  60.         prev = &ef->leaf->efrags;
  61.         while (1)
  62.         {
  63.             walk = *prev;
  64.             if (!walk)
  65.                 break;
  66.             if (walk == ef)
  67.             {    // remove this fragment
  68.                 *prev = ef->leafnext;
  69.                 break;
  70.             }
  71.             else
  72.                 prev = &walk->leafnext;
  73.         }
  74.                 
  75.         old = ef;
  76.         ef = ef->entnext;
  77.         
  78.     // put it on the free list
  79.         old->entnext = cl.free_efrags;
  80.         cl.free_efrags = old;
  81.     }
  82.     
  83.     ent->efrag = NULL; 
  84. }
  85.  
  86. /*
  87. ===================
  88. R_SplitEntityOnNode
  89. ===================
  90. */
  91. void R_SplitEntityOnNode (mnode_t *node)
  92. {
  93.     efrag_t        *ef;
  94.     mplane_t    *splitplane;
  95.     mleaf_t        *leaf;
  96.     int            sides;
  97.     
  98.     if (node->contents == CONTENTS_SOLID)
  99.     {
  100.         return;
  101.     }
  102.     
  103. // add an efrag if the node is a leaf
  104.  
  105.     if ( node->contents < 0)
  106.     {
  107.         if (!r_pefragtopnode)
  108.             r_pefragtopnode = node;
  109.  
  110.         leaf = (mleaf_t *)node;
  111.  
  112. // grab an efrag off the free list
  113.         ef = cl.free_efrags;
  114.         if (!ef)
  115.         {
  116.             Con_Printf ("Too many efrags!\n");
  117.             return;        // no free fragments...
  118.         }
  119.         cl.free_efrags = cl.free_efrags->entnext;
  120.  
  121.         ef->entity = r_addent;
  122.         
  123. // add the entity link    
  124.         *lastlink = ef;
  125.         lastlink = &ef->entnext;
  126.         ef->entnext = NULL;
  127.         
  128. // set the leaf links
  129.         ef->leaf = leaf;
  130.         ef->leafnext = leaf->efrags;
  131.         leaf->efrags = ef;
  132.             
  133.         return;
  134.     }
  135.     
  136. // NODE_MIXED
  137.  
  138.     splitplane = node->plane;
  139.     sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  140.     
  141.     if (sides == 3)
  142.     {
  143.     // split on this plane
  144.     // if this is the first splitter of this bmodel, remember it
  145.         if (!r_pefragtopnode)
  146.             r_pefragtopnode = node;
  147.     }
  148.     
  149. // recurse down the contacted sides
  150.     if (sides & 1)
  151.         R_SplitEntityOnNode (node->children[0]);
  152.         
  153.     if (sides & 2)
  154.         R_SplitEntityOnNode (node->children[1]);
  155. }
  156.  
  157.  
  158. /*
  159. ===================
  160. R_SplitEntityOnNode2
  161. ===================
  162. */
  163. void R_SplitEntityOnNode2 (mnode_t *node)
  164. {
  165.     mplane_t    *splitplane;
  166.     int            sides;
  167.  
  168.     if (node->visframe != r_visframecount)
  169.         return;
  170.     
  171.     if (node->contents < 0)
  172.     {
  173.         if (node->contents != CONTENTS_SOLID)
  174.             r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
  175.                                     //  visible and not BSP clipped
  176.         return;
  177.     }
  178.     
  179.     splitplane = node->plane;
  180.     sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  181.     
  182.     if (sides == 3)
  183.     {
  184.     // remember first splitter
  185.         r_pefragtopnode = node;
  186.         return;
  187.     }
  188.     
  189. // not split yet; recurse down the contacted side
  190.     if (sides & 1)
  191.         R_SplitEntityOnNode2 (node->children[0]);
  192.     else
  193.         R_SplitEntityOnNode2 (node->children[1]);
  194. }
  195.  
  196.  
  197. /*
  198. ===========
  199. R_AddEfrags
  200. ===========
  201. */
  202. void R_AddEfrags (entity_t *ent)
  203. {
  204.     model_t        *entmodel;
  205.     int            i;
  206.         
  207.     if (!ent->model)
  208.         return;
  209.  
  210.     if (ent == cl_entities)
  211.         return;        // never add the world
  212.  
  213.     r_addent = ent;
  214.             
  215.     lastlink = &ent->efrag;
  216.     r_pefragtopnode = NULL;
  217.     
  218.     entmodel = ent->model;
  219.  
  220.     for (i=0 ; i<3 ; i++)
  221.     {
  222.         r_emins[i] = ent->origin[i] + entmodel->mins[i];
  223.         r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
  224.     }
  225.  
  226.     R_SplitEntityOnNode (cl.worldmodel->nodes);
  227.  
  228.     ent->topnode = r_pefragtopnode;
  229. }
  230.  
  231.  
  232. /*
  233. ================
  234. R_StoreEfrags
  235.  
  236. // FIXME: a lot of this goes away with edge-based
  237. ================
  238. */
  239. void R_StoreEfrags (efrag_t **ppefrag)
  240. {
  241.     entity_t    *pent;
  242.     model_t        *clmodel;
  243.     efrag_t        *pefrag;
  244.  
  245.  
  246.     while ((pefrag = *ppefrag) != NULL)
  247.     {
  248.         pent = pefrag->entity;
  249.         clmodel = pent->model;
  250.  
  251.         switch (clmodel->type)
  252.         {
  253.         case mod_alias:
  254.         case mod_brush:
  255.         case mod_sprite:
  256.             pent = pefrag->entity;
  257.  
  258.             if ((pent->visframe != r_framecount) &&
  259.                 (cl_numvisedicts < MAX_VISEDICTS))
  260.             {
  261.                 cl_visedicts[cl_numvisedicts++] = pent;
  262.  
  263.             // mark that we've recorded this entity for this frame
  264.                 pent->visframe = r_framecount;
  265.             }
  266.  
  267.             ppefrag = &pefrag->leafnext;
  268.             break;
  269.  
  270.         default:    
  271.             Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
  272.         }
  273.     }
  274. }
  275.  
  276.  
  277.